/*global pi */
// 模板的编解码模块
// <!--{#name/}--> 表示根对象的name变量，
// <!--{#player.name/}--> 表示根对象中player对象的name变量，
// <!--{$name/}--> 表示当前对象中的name变量，
// <!--{$player.name/}--> 表示当前对象中player对象的name变量，
// <!--{$list}--> <BR><!--{$show/}-->&nbsp;<!--{#name/}-->&nbsp;<!--{#group.xyz/}--><BR> <!--{/$list}-->
//		表示当前对象中以list为名的列表，并循环该列表，
// <!--{$list}--> <BR><!--{$/}--> <!--{$[1]/}--><!--{/$list}-->
//		$表示列表中的每个元素，$[1]表示列表中的每个元素（必须是列表）的第1元素
// <!--{$list[1]/}--> 表示当前对象中list列表的第一个元素，注意：[]内不能为变量
// <!--{$list[1].name/}--> 表示当前对象中list列表的第一个元素name变量，
// <!--{length($list)/}--> 调用函数length，取当前对象中list列表的长度，
// <!--{tl($list)}--> <BR><!--{$show/}-->&nbsp;<!--{#name/}--><BR> <!--{/tl($list)}-->
//		调用函数tl，参数为当前对象中以list为名的列表，返回从list第2个元素开始的新列表
// <!--{lists.nthtail(2, $list)}--> <BR><!--{$show/}-->&nbsp;<!--{#name/}--><BR> <!--{/lists.nthtail(2, $list)}-->
//		调用函数lists.nthtail，参数2为当前对象中以list为名的列表，返回从list第2个元素开始的新列表

pi.mod.define('pi.template', function(pi){
	"use strict";
	// 定义模块对象
	var module = {},

	// 找到前缀进行编码
	encode_prefix = function(str, start, template, array, line){
		var sub, i = str.indexOf("<!--{", start);
		if(i < 0){
			if(array.length > 0){
				throw("end without match, name = " + template.name +", line : " + line);
			}
			template.arr.push(str.slice(start));
			return template;
		}
		if(i > start){
			sub = str.substring(start, i);
			template.arr.push(sub);
			return encode_suffix(str, i + 5, template, array, line + pi.str.count(sub, "\n"));
		}
		return encode_suffix(str, i + 5, template, array, line);
	},
	// 找到后缀进行编码
	encode_suffix = function(str, start, template, array, line){
		var sub, i = str.indexOf("}-->", start);
		if(i < 0){
			throw("must be end with suffix, name = " + template.name +", line : " + line);
		}
		if(i > start){
			sub = str.substring(start, i);
			return parse(sub, str, i + 4, template, array, line + pi.str.count(sub, "\n"));
		}
		throw("var is null, name = " + template.name +", line : " + line);
	},
	// 分析变量的类型
	parse = function(sub, str, start, template, array, line){
		var t, len;
		if(sub.charAt(0) === '/'){
			// 列表模板结束
			sub = sub.slice(1);
			if(sub != template.name){
				throw("list does not match, name = " + sub +", line : " + line);
			}
			len = array.length;
			if(len === 0){
				throw("root match end, name = " + sub +", line : " + line);
			}
			len --;
			t = array[len];
			t.arr.push(template);
			array.length = len;
			return encode_prefix(str, start, t, array, line);
		}
		len = sub.length - 1;
		if(sub.charAt(len) === "/"){
			// 变量
			sub = sub.slice(0, len);
			template.arr.push({name:sub, type:parse_name(sub, line)});
			return encode_prefix(str, start, template, array, line);
		};
		// 列表模板开始
		array.push(template);
		return encode_prefix(str, start,
			{name:sub, type:parse_name(sub, line), arr:[]}, array, line);
	},
	// 分析变量名称
	parse_name = function(name, line){
		var c = name.charAt(0), i, j;
		if(c === "#" || c === "$"){
			// 根对象或当前对象
			return [c, parse_name_list(name.slice(1).split("."), name, line)];
		}
		i = name.indexOf("(");
		if(i < 0){
			try{
				return [",", JSON.parse(name)];
			}catch (e){
				throw("invalid json, name = " + name +", line : " + line);
			}
		}
		j = name.indexOf(")", i + 1);
		if(j < 0){
			throw("fun without match, name = " + name +", line : " + line);
		}
		return [".", name.slice(0, i).split("."),
			parse_args(name.slice(i + 1, j), line),
			parse_name_list(name.slice(j + 1).split("."), name, line)];
	},
	// 分析变量名称数组
	parse_name_list = function(arr, name, line){
		var i, n, s, result = [], start, end, v;
		for(i = 0, n = arr.length; i < n; i ++){
			s = arr[i];
			if(s.length === 0){
				throw("zero length string, name = " + name +", line : " + line);
			}
			start = s.indexOf("[");
			if(start < 0){
				result.push(s);
				continue;
			}
			end = s.indexOf("]", start + 1);
			if(end < 0){
				throw("element without match, name = " + name +", line : " + line);
			}
			v = parseInt(s.slice(start + 1, end), 10);
			if(isNaN(v)){
				throw("index must be integer, name = " + name +", line : " + line);
			}
			if(start > 0){
				result.push(s.slice(0, start));
			}
			result.push(v);
			if(s.length === end + 1){
			}else if(s.charAt(end + 1) === "["){
				arr[i --] = s.slice(end + 1);
			}else{
				throw("invaid char, name = " + name +", line : " + line);
			}
		}
		return result;
	},
	// 分析函数参数
	parse_args = function(str, line){
		var arr = str.split(","), i;
		for(i = arr.length - 1; i >= 0; i --){
			arr[i] = parse_name(pi.str.strip(arr[i]), line);
		}
		return arr;
	},

	// 解码模板到result中
	decode = function(arr, root, cur, result){
		var i, n, e, list;
		for(i = 0, n = arr.length; i < n; i ++){
			e = arr[i];
			if(pi.lang.isString(e)){
				result.push(e);
			}else if(e.arr){
				list = get_list(root, cur, e.type);
				if(list){
					decode_list(e.arr, root, list, result);
				}
			}else{
				decode_var(root, cur, e.type, result);
			}
		}
	},
	// 循环列表，解码列表到result中
	decode_list = function(list, root, arr, result){
		var i, n;
		for(i = 0, n = arr.length; i < n; i ++){
			decode(list, root, arr[i], result);
		}
	},
	// 解码变量所对应的值到result中
	decode_var = function(root, cur, type, result){
		result.push(get_var(root, cur, type));
	},
	// 根据名字，获得对应的列表
	get_list = function(root, cur, type){
		var v = get_var(Root, Cur, type);
		return pi.lang.isArray(v) ? v : false;
	},
	// 根据名字，获得值
	get_var = function(root, cur, type){
		var t = type[0], arr, i, n;
		if(t === "#"){
			return get_var1(root, type[1]);
		}else if(t === "$"){
			return get_var1(cur, type[1]);
		}else if(t === ","){
			return type[1];
		}else if(t === "."){
			t = get_var1(self, type[1]);
			if(pi.lang.isFunction(t)){
				arr = type[2];
				for(i = 0, n = arr.length; i < n; i ++){
					arr[i] = get_var(root, cur, arr[i]);
				};
				t = t.apply(undefined, arr);
				return (t != undefined) ? get_var1(t, type[3]) : "";
			}
		}
		return "";
	},
	// 根据名字，从当前的对象中获得值
	get_var1 = function(obj, arr){
		var i, n, e;
		for(i = 0, n = arr.length; i < n; i ++){
			e = arr[i];
			obj = obj[e];
			if(obj === undefined){
				return "";
			}
		}
		return obj;
	};

	// 编码模板
	module.encode = function(str){
		return encode_prefix(str, 0, {name:"", type:[], arr:[]}, [], 1);
	};
	// 解码模板
	module.decode = function(t, root){
		var result = [];
		decode(t.arr, root, root, result);
		return result.join("");
	};
	return module;
});
